#!/bin/sh
#
#Create a file of a blurred LSST image.
#Usage:  lsstspot <paramfile>
#
# ---------------------------------------------------------------------
# This script file is a front-end to the trace program.
# It defines necessary environment variables and then runs the binary.
# It is designed to be relocatable!  One logical link to it is allowed!
#
#How does this file work?  It doubles as a shell script and a tcl script!
#(Ousterhout's hack).  TCL continues comment lines that end with a backslash,
#where as sh does not.  So, we run it as a shell script and then source the
#same file as a tcl script.  The shell commands are ignored by TCL.
#
#The shell commands get the absolute path of the script (and allows for
#dereferencing one link to the script!).  I assume that the "trace" program is
#colocated in the same directory.  All other command-line arguments are
#passed to the trace program.  This file is sourced by trace, the shell
#commands are passed over, and the tcl commands are picked up.
#
#Trace is run with the -noTk flag. The -file flag tells it to read this
#file.  The "--" tells TclX to not treat any remaining command line arguments
#as a file name.
#
#=======================================================================
#!/bin/sh
#Prefix arg0 with current path if arg0 is a relative path
# \
CWD=`pwd`; \
ARG0=`echo $0 | sed -e "s%^\([^/]\)%$CWD/\1%"`; \
ARG0=`ls -l $ARG0 | awk '{ print $NF }'`; \
DIRECTORY=`echo $ARG0 | sed -e 's%/[^/]*$%%'`; \
exec ${DIRECTORY}/trace -noTk -file "$0" -- ${1+"$@"} </dev/null >/dev/null

echo Input arguments are $argv

proc usage {} {
   puts stderr {USAGE: "lsstspot <paramfile>"}
   puts stderr {Optional parameters:}
   puts stderr ""
   puts stderr \
	{    SCALE   Size of one pixel in arcsec (.05 is nice)}
   puts stderr \
	{    NPIX    Total size of image (128 is nice)}
   puts stderr \
	{    SIGMA   Blur in arcsec (to smooth out spot diagram) (.2 is nice)}
   puts stderr \
	{    FILTER  Filter 1 to 6 for U, B, V, R, I, Z}
   puts stderr \
	{    XMM     Position in the focal plane (max 275 mm radius)}
   puts stderr \
	{    YMM }
   puts stderr \
	{    OUTPUT  Name of output file (default is spot4.fit)}
   puts stderr ""
   puts stderr {    X surf offset	(mm)}
   puts stderr {    Y surf offset	(mm)}
   puts stderr {    Z surf offset	(mm)}
   puts stderr {    THETA surf offset	(radians)}
   puts stderr {    PHI surf offset	(radians)}
   puts stderr {    CURV surf offset	(inverse mm)}
   puts stderr {    CCON surf offset	(dimensionless)}
   puts stderr \
	{    surf: 1 = primary, 2 = secondary, 3 = tertiary}
   puts stderr \
	{    surf: 4 = Lens C1, 5 = Lens C2,   6 = filter}
   puts stderr \
	{    surf: 7 = Lens C3, 8 = focal plane}
   exit 1
   }

#Check for valid input
if {![info complete $argv]} usage
if {[llength $argv] != 1} usage
set paramfile [string trim $argv]
if {![file exists $paramfile]} {
   puts stderr "Error: No parameter file $paramfile"
   exit 1
   }

#Defaults
set SCALE .05
set NPIX 128
set FILTER 4
set XMM 0
set YMM 0

set fid [open $paramfile]
while {1} {
   set line [string trim [gets $fid]]
   if {[eof $fid]} break
   if {[string index $line 0] == "#"} continue
   if {[string length $line] == 0} continue
   if {![info complete $line]} {
	puts stderr "Bad line in parameter file: $line"
	close $fid
	exit 1
	}
   set param [string toupper [lindex $line 0]]
   foreach name "SCALE NPIX SIGMA FILTER XMM YMM OUTPUT" {
	if {$param == "$name"} {
	   set val [lindex $line 1]
	   set $name $val

#Validate value
	   foreach option "NPIX FILTER" {
		if {$param == "$option"} {
		   if {![ctype digit $val]} {
			close $fid
			puts stderr "Bad value $val for parameter $param"
			exit 1
			}
		   }
		}
	   foreach option "SCALE SIGMA XMM YMM" {
		if {$param == "$option"} {
		   if {[catch {format %f $val}]} {
			close $fid
			puts stderr "Bad value $val for parameter $param"
			exit 1
			}
		   }
		}
	   }
	}

   foreach name "X Y Z THETA PHI CURV CCON" {
	if {$param == "$name"} {
	   set surf [lindex $line 1]
	   if {![ctype digit $surf]} {
		puts stderr "Bad surface identifier $surf"
		exit 1
		}
	   if {$surf < 1 || $surf > 8} {
		puts stderr "Surface identifier $surf out of bounds"
		exit 1
		}

	   set val [lindex $line 2]
	   if {[catch {format %f $val}]} {
		puts stderr "Bad value $val for parameter $param"
		close $fid
		exit 1
		}
	   set ${name}($surf) $val
	   }
	}
   }
close $fid

#Only R filter is in design, so fix here
set FILTER 4
if {![info exists OUTPUT]} {
   set OUTPUT spot$FILTER.fit
   }

#Convert FILTER to internal icolor, since each filter has 2 wavelengths
   set ICOLOR [expr 2*$FILTER-1]

#Check that output directory is writable
set dir [file dirname $OUTPUT]
if {![file writable $dir]} {
   puts stderr "Output directory $dir is not writable!"
   exit 1
   }

#Read the LSST design
set optic [lensRead lsst]

#Dense grid of points
rayPattern $optic 12 2

#Update optical design

#So far I can only tweak mirrors and the focal plane, since I need more
#logic to handle lenses.
foreach name "X Y Z THETA PHI CURV CCON" {
   foreach surf "1 2 3 8" {
	if {[info exists ${name}($surf)]} {
	   if {$surf == 1} {
	   	set isurf [format %02f [expr $isurf + $FILTER/100.]]
	   } elseif {$surf == 8} {
		set isurf 13
	   } else {
		set isurf [expr $surf+1]
		}
	   set param [string tolower $name]
	   set val0 [showSurf $optic $isurf $param]
	   set val [expr $val0 + [set ${name}($surf)]]
	   setSurf $optic $isurf $param $val
	   }
	}
   }

#Now we have logic to tweak lenses.  I will not tweak shapes because I would
#want to go back to the single surface case.
foreach name "X Y Z THETA PHI" {
   foreach surf "4 5 6 7" {
	if {[info exists ${name}($surf)]} {
	   set surf1 [expr $surf*2-3]
	   set surf2 [expr $surf1+1]
	   set param [string tolower $name]

#For Z position, I tweak each surface individually
	   if {$name == "Z"} {
		foreach isurf "$surf1 $surf2" {
		   set val0 [showSurf $optic $isurf $param]
		   set val [expr $val0 + [set ${name}($surf)]]
		   setSurf $optic $isurf $param $val
		   }

#For all other params, both surfaces of lens have same value.
	   } else {
		set val0 [showSurf $optic $surf1 $param]
		set val [expr $val0 + [set ${name}($surf)]]
		setLensSurf $optic $surf1 $surf2 $param $val
		}
	   }
	}
   }

spotMap $optic $XMM $YMM $ICOLOR
set tempfile spot.fit
if {"$tempfile" != "$OUTPUT"} {
   exec cp $tempfile $OUTPUT
   exec rm $tempfile
   }

exit 0
